import socket
import threading
import time
from datetime import datetime
import queue
import binascii

class TTSController:
    def __init__(self, ip="192.168.1.65", port=50000):
        # TCP客户端连接变量
        self.client = None
        self.ip = ip
        self.port = port
        
        # 创建数据队列
        self.send_queue = queue.Queue(maxsize=100)
        self.data_queue = queue.Queue(maxsize=100)
        
        # TTS参数默认值
        """
        "2": 晓玲（女声）
        "3": 尹小坚（男声）
        "4": 易小强（男声） 
        "5": 田蓓蓓（女声）
        "6": 唐老鸭（效果器）
        "7": 小燕子（女童声）
        """
        self.voice = "3"       # 尹小坚(男声)
        self.speed = "5"       # 语速 (0-10)
        self.pitch = "5"       # 语调 (0-10)
        self.volume = "5"      # 音量 (0-10)
        self.number_mode = "0" # 数字处理策略 (0:自动判断, 1:数字做号码, 2:数字做数值)
        self.pinyin = "0"      # 识别汉语拼音 (0:关闭, 1:开启)
        self.punctuation = "0" # 朗读标点符号 (0:关闭, 1:开启)
        self.style = "1"       # 发音风格 (0:一字一顿, 1:平铺直叙)
        self.name_mode = "0"   # 姓名读音策略 (0:自动判断, 1:按姓氏读, 2:开头按姓氏)
        self.one_mode = "1"    # 号码中"1"的读法 (0:读作'幺', 1:读作'一')
        self.rhythm = "0"      # 处理韵律标注 (0:关闭, 1:开启)
        
        self.connected = False
        self.debug = False
        
        # 启动UI更新线程
        self.start_log_thread()
    
    def log(self, message):
        """记录日志"""
        current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        log_message = f"{current_time}   {message}"
        if self.debug:
            print(log_message)
        self.data_queue.put(log_message)
    
    def start_log_thread(self):
        """启动日志处理线程"""
        def process_log():
            while True:
                try:
                    message = self.data_queue.get(timeout=0.1)
                    # 这里可以处理日志，例如写入文件等
                    if self.debug:
                        print(message)
                except queue.Empty:
                    pass
                except Exception as e:
                    print(f"日志处理错误: {e}")
                time.sleep(0.1)
        
        log_thread = threading.Thread(target=process_log, daemon=True)
        log_thread.start()
    
    def connect(self, ip=None, port=None):
        """连接到服务器"""
        try:
            if self.client and self.client.fileno() != -1:
                self.log("已经连接")
                return True
            
            self.ip = ip if ip else self.ip
            self.port = port if port else self.port
            
            # 创建TCP连接
            self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.client.connect((self.ip, self.port))
            
            self.log("连接成功")
            self.connected = True
            
            # 启动接收线程
            read_thread = threading.Thread(target=self.read_data_thread, daemon=True)
            read_thread.start()
            
            # 启动发送线程
            send_thread = threading.Thread(target=self.send_data_thread, daemon=True)
            send_thread.start()
            
            return True
            
        except Exception as e:
            self.log(f"连接失败: {str(e)}")
            print(f"连接错误: {e}")
            return False
    
    def close(self):
        """关闭连接"""
        if self.client:
            try:
                self.client.close()
                self.client = None
                self.connected = False
                # 发送空字符串以结束发送线程的等待
                self.send_queue.put("")
                self.log("关闭连接")
                return True
            except Exception as e:
                print(f"关闭连接错误: {e}")
                return False
        return True
    
    def send_text(self, text):
        """发送文本到TTS设备"""
        try:
            if text:
                self.send_queue.put("#" + text)
                self.log("发送：#" + text)
                return True
            return False
        except Exception as e:
            print(f"发送文本错误: {e}")
            return False
    
    def read_data_thread(self):
        """数据接收线程"""
        try:
            while self.client and self.connected:
                if not self.client or self.client.fileno() == -1:
                    self.log("退出接收线程")
                    return
                
                # 接收数据
                try:
                    data = self.client.recv(1024)
                    if data:
                        # 将数据转换为十六进制字符串
                        hex_data = binascii.hexlify(data).decode().upper()
                        
                        # 判断特定响应
                        if hex_data == "4F4B":
                            self.log("收到回复！OK")
                        elif hex_data == "0800":
                            self.log("收到回复！OL")
                        else:
                            self.log(f"收到回复：{hex_data}")
                    else:
                        self.log("数据读取完毕！")
                        self.close()
                        return
                except Exception as e:
                    self.log(f"接收错误: {str(e)}")
                    self.close()
                    return
                
                time.sleep(0.1)
        except Exception as e:
            self.log(f"接收线程错误: {str(e)}")
            return
    
    def send_data_thread(self):
        """数据发送线程"""
        try:
            while self.connected:
                if not self.client:
                    self.log("退出发送线程")
                    return
                
                message = self.send_queue.get()
                
                if not message:  # 空消息用于结束线程
                    self.log("退出发送线程")
                    return
                
                if not self.client or self.client.fileno() == -1:
                    self.log("退出发送线程")
                    return
                
                # 编码并发送数据
                encoded_bytes = message.encode('gb2312')
                self.client.sendall(encoded_bytes)
                
                time.sleep(0.5)
        except Exception as e:
            self.log(f"发送线程错误: {str(e)}")
            return
    
    # TTS参数设置方法
    def set_voice(self, voice):
        """设置发音人
        voice: 
            "2": 晓玲(女声)
            "3": 尹小坚(男声)
            "4": 易小强(男声)
            "5": 田蓓蓓(女声)
            "6": 唐老鸭(效果器)
            "7": 小燕子(女童声)
        """
        self.voice = voice
        return self
    
    def set_speed(self, speed):
        """设置语速 (0-10)"""
        self.speed = str(speed)
        return self
    
    def set_pitch(self, pitch):
        """设置语调 (0-10)"""
        self.pitch = str(pitch)
        return self
    
    def set_volume(self, volume):
        """设置音量 (0-10)"""
        self.volume = str(volume)
        return self
    
    def set_number_mode(self, mode):
        """设置数字处理策略
        mode:
            "0": 自动判断
            "1": 数字做号码
            "2": 数字做数值
        """
        self.number_mode = mode
        return self
    
    def set_pinyin(self, enabled):
        """设置是否识别汉语拼音"""
        self.pinyin = "1" if enabled else "0"
        return self
    
    def set_punctuation(self, enabled):
        """设置是否朗读标点符号"""
        self.punctuation = "1" if enabled else "0"
        return self
    
    def set_style(self, style):
        """设置发音风格
        style:
            "0": 一字一顿
            "1": 平铺直叙
        """
        self.style = style
        return self
    
    def set_name_mode(self, mode):
        """设置姓名读音策略
        mode:
            "0": 自动判断
            "1": 按姓氏读
            "2": 开头按姓氏
        """
        self.name_mode = mode
        return self
    
    def set_one_mode(self, mode):
        """设置号码中"1"的读法
        mode:
            "0": 读作'幺'
            "1": 读作'一'
        """
        self.one_mode = mode
        return self
    
    def set_rhythm(self, enabled):
        """设置是否处理韵律标注"""
        self.rhythm = "1" if enabled else "0"
        return self
    
    def reset_settings(self):
        """重置TTS设置为默认值"""
        # 默认值设置，除发音人外
        self.speed = "5"
        self.pitch = "5" 
        self.volume = "5"
        self.number_mode = "0"
        self.style = "1"
        self.name_mode = "0"
        self.one_mode = "0"
        self.pinyin = "0"
        self.punctuation = "0"
        self.rhythm = "0"
        
        # 发送重置命令
        try:
            self.send_queue.put("#[d]")
            self.log("已重置为默认设置")
            return True
        except Exception as e:
            print(f"重置设置错误: {e}")
            return False
    
    def apply_settings(self):
        """应用TTS设置"""
        settings = ""
        # 发音人
        settings += f"[m{self.voice}]"
        # 语速
        settings += f"[s{self.speed}]"
        # 语调
        settings += f"[t{self.pitch}]"
        # 音量
        settings += f"[v{self.volume}]"
        # 数字处理
        settings += f"[n{self.number_mode}]"
        # 识别拼音
        settings += f"[i{self.pinyin}]"
        # 标点朗读
        settings += f"[b{self.punctuation}]"
        # 发音风格
        settings += f"[f{self.style}]"
        # 姓名读音策略
        settings += f"[r{self.name_mode}]"
        # 号码中"1"的读法
        settings += f"[y{self.one_mode}]"
        # 韵律标注处理策略
        settings += f"[z{self.rhythm}]"
        
        try:
            # 将设置发送到队列
            self.send_queue.put("#" + settings)
            self.log("发送设置：#" + settings)
            return True
        except Exception as e:
            print(f"应用设置错误: {e}")
            return False
    
    def set_debug(self, enabled):
        """设置是否输出调试信息"""
        self.debug = enabled
        return self
    
    @staticmethod
    def hex_string_to_byte_array(hex_string):
        """十六进制字符串转换为字节数组"""
        hex_string = hex_string.replace(" ", "")
        length = len(hex_string)
        if length % 2 != 0:
            length += 1
            hex_string = "0" + hex_string
        
        return binascii.unhexlify(hex_string)
    
    @staticmethod
    def bytes_to_hex(data):
        """字节数组转换为十六进制字符串"""
        return binascii.hexlify(data).decode().upper()


# 使用示例
def main():
    # 创建TTS控制器实例
    tts = TTSController()
    tts.set_debug(True)
    
    # 连接到设备
    if tts.connect():
        # 设置TTS参数
        tts.set_voice("2")  # 晓玲(女声)
        tts.set_speed(6)    # 语速稍快
        tts.set_volume(7)   # 音量较大
        tts.apply_settings()
        
        # 发送测试文本
        tts.send_text("这是一个测试消息，无需界面也能控制语音播放。")
        
        # 等待一段时间后关闭连接
        time.sleep(5)
        tts.close()

if __name__ == "__main__":
    main()

# 功能说明_扩展实现

# 1. 发音人选择 [m*] - 允许选择不同的声音
#    - [m2]: 晓玲（女声）
#    - [m3]: 尹小坚（男声）
#    - [m4]: 易小强（男声）
#    - [m5]: 田蓓蓓（女声）
#    - [m6]: 唐老鸭（效果器）
#    - [m7]: 小燕子（女童声）
# 2. 语速控制 [s*] - 0-10级调节语速
# 3. 语调控制 [t*] - 0-10级调节语调
# 4. 音量控制 [v*] - 0-10级调节音量
# 5. 数字处理策略 [n*] - 选择自动判断/号码处理/数值处理
# 6. 识别汉语拼音 [i*] - 启用/禁用拼音识别
# 7. 标点符号朗读 [b*] - 启用/禁用标点朗读
# 8. 发音风格 [f*] - 一字一顿(0)或平铺直叙(1)
# 9. 姓名读音策略 [r*] - 自动判断(0)/强制以姓氏读(1)/句开头按姓氏读(2)
# 10. 号码中"1"的读法 [y*] - 读作"幺"(0)或读作"一"(1)
# 11. 韵律标注处理 [z*] - 处理韵律标注(使用"#"和"*"标记)
# 12. 重置默认设置 [d] - 恢复所有设置为默认值(除发音人外)

# # 使用方法

# 1. 创建TTSController实例，可指定IP和端口
#    tts = TTSController(ip="192.168.1.65", port=50000)
# 
# 2. 连接到设备
#    tts.connect()
#
# 3. 设置TTS参数（链式调用）
#    tts.set_voice("3").set_speed(6).set_volume(8)
#
# 4. 应用设置
#    tts.apply_settings()
#
# 5. 发送文本
#    tts.send_text("要播放的文本内容")
#
# 6. 关闭连接
#    tts.close()
#
# 7. 调试输出控制
#    tts.set_debug(True)  # 开启调试输出